using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Business.WarehouseLocationManagement.Dto;
using Business.Models;
using Microsoft.AspNetCore.Authorization;
using Business.Permissions;

namespace Business.WarehouseLocationManagement
{
    [Authorize(BusinessPermissions.WarehouseLocation.Default)]
    public class WarehouseLocationAppService : ApplicationService, IWarehouseLocationAppService
    {
        private const string FormName = "WarehouseLocation";
        private IRepository<WarehouseLocation, Guid> _repository;
        private IRepository<Warehouse, Guid> _warehouseRepository;
        private IRepository<Area, Guid> _areaRepository;
        private IRepository<WarehouseArea, Guid> _warehouseAreaRepository;


        //public WarehouseLocationAppService(
        //    IRepository<WarehouseLocation, Guid> repository
        //    )
        //{
        //    _repository = repository;
        //}

        public WarehouseLocationAppService(IRepository<WarehouseLocation, Guid> repository, IRepository<Warehouse, Guid> warehouseRepository, IRepository<Area, Guid> areaRepository, IRepository<WarehouseArea, Guid> warehouseAreaRepository)
        {
            _repository = repository;
            _warehouseRepository = warehouseRepository;
            _areaRepository = areaRepository;
            _warehouseAreaRepository = warehouseAreaRepository;
        }

        #region 增删改查基础方法

        public async Task<WarehouseLocationDto> Get(Guid id)
        {
            var data = await _repository.GetAsync(id);
            var dto = ObjectMapper.Map<WarehouseLocation, WarehouseLocationDto>(data);
            return dto;
        }

        public async Task<List<WarehouseLocationDto>> GetList()
        {
            var data = await _repository.GetListAsync();
            var dto = ObjectMapper.Map<List<WarehouseLocation>, List<WarehouseLocationDto>>(data);
            return dto;
        }

        public async Task<PagedResultDto<LocationDto>> GetAll(GetWarehouseLocationInputDto input)
        {
            //var query = (await _repository.GetQueryableAsync()).WhereIf(!string.IsNullOrWhiteSpace(input.Filter), a => a.PCode .Contains(input.Filter));
            //var query = (await _repository.GetQueryableAsync()).WhereIf(!string.IsNullOrWhiteSpace(input.WarehouseId ), a => a.WarehouseId.ToUpper() == input.WarehouseId.ToUpper()).WhereIf(!string.IsNullOrWhiteSpace(input.AreaId), a => a.AreaId.ToUpper() == input.AreaId.ToUpper()).WhereIf(!string.IsNullOrWhiteSpace(input.Filter), a => a.PCode.ToUpper() == input.Filter.ToUpper());
            var warehouseList = await _warehouseRepository.GetQueryableAsync();
            var warehouseAreas = await _warehouseAreaRepository.GetQueryableAsync();
            var areaList = await _areaRepository.GetQueryableAsync();
            var warehouseLocation = await _repository.GetQueryableAsync();
            var query = (from a in warehouseList
                         join b in areaList on a.Id.ToString().ToUpper() equals b.PCode.ToUpper()
                         join c in warehouseAreas on b.Id.ToString().ToUpper() equals c.PCode.ToUpper()
                         join d in warehouseLocation on c.Id.ToString().ToUpper() equals d.PCode.ToUpper()
                         select new LocationDto
                         {
                             WarehouseId = a.Id.ToString().ToUpper(),
                             AreaId = b.Id.ToString().ToUpper(),
                             PCode = c.Id.ToString().ToUpper(),
                             WarehouseAreaName = c.Name,
                             Code = d.Code,
                             LocationType = d.LocationType,
                             LocationHeight = d.LocationHeight,
                             LocationWidth = d.LocationWidth,
                             LocationLength = d.LocationLength,
                             LocationVolume = d.LocationVolume,
                             ExclusionHistory = d.ExclusionHistory,
                             GoodsShelf = d.GoodsShelf,
                             ExclusionMargin = d.ExclusionMargin,
                             IsMixing = d.IsMixing,
                             LoadBearing = d.LoadBearing,
                             Id = d.Id,
                             Laneway = d.Laneway,
                             Layer = d.Layer,
                             LocationException = d.LocationException,
                             LocationLabel = d.LocationLabel,
                             LockPriority = d.LockPriority,
                             PathPriority = d.PathPriority,
                             Place = d.Place,
                             PriorityGoods = d.PriorityGoods,
                             UsedLoadBearing = d.UsedLoadBearing,
                             UsedVolume = d.UsedVolume,
                             UsePattern = d.UsePattern,
                         });
            query = query
               .WhereIf(!string.IsNullOrWhiteSpace(input.WarehouseId), a => a.WarehouseId.ToUpper() == input.WarehouseId.ToUpper())
               .WhereIf(!string.IsNullOrWhiteSpace(input.AreaId), a => a.AreaId.ToUpper() == input.AreaId.ToUpper())
               .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), a => a.PCode.ToUpper() == input.Filter.ToUpper());

            var totalCount = await query.CountAsync();
            var items = await query.OrderBy(input.Sorting ?? "Id")
                       .Skip(input.SkipCount)
                       .Take(input.MaxResultCount)
                       .ToListAsync();

            //var dto = ObjectMapper.Map<List<WarehouseLocation>, List<WarehouseLocationDto>>(items);
            return new PagedResultDto<LocationDto>(totalCount, items);
        }

        public async Task<WarehouseLocationDto> DataPost(CreateOrUpdateWarehouseLocationDto input)
        {
            WarehouseLocation result = null;
            if (!input.Id.HasValue)
            {
                input.Id = GuidGenerator.Create();
                result = await _repository.InsertAsync(ObjectMapper.Map<CreateOrUpdateWarehouseLocationDto, WarehouseLocation>(input));
            }
            else
            {
                var data = await _repository.GetAsync(input.Id.Value);
                result = await _repository.UpdateAsync(ObjectMapper.Map(input, data));
            }
            return ObjectMapper.Map<WarehouseLocation, WarehouseLocationDto>(result);
        }

        public async Task Delete(List<Guid> ids)
        {
            foreach (var item in ids)
            {
                await _repository.DeleteAsync(item);
            }

        }


        #endregion

    }
}